package us.wili.dev.client.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import me.chanjar.weixin.common.error.WxErrorException;
import org.apache.commons.lang3.RandomUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import us.wili.dev.client.dao.ClientUserMapper;
import us.wili.dev.client.jwt.JwtSessionUtil;
import us.wili.dev.client.jwt.JwtUser;
import us.wili.dev.client.model.req.MiniGetUserInfoReq;
import us.wili.dev.client.model.rsp.AboutMeRsp;
import us.wili.dev.client.model.rsp.MiniUserInfoRsp;
import us.wili.dev.client.service.ClientUserService;
import us.wili.dev.exception.ErrorCode;
import us.wili.dev.exception.UserException;
import us.wili.dev.jwt.model.ChannelEnum;
import us.wili.dev.jwt.session.redis.RedisSession;
import us.wili.dev.model.entity.User;
import us.wili.dev.model.example.UserExample;
import us.wili.dev.service.impl.BaseUserServiceImpl;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.function.Supplier;

@Service
public class ClientUserServiceImpl extends BaseUserServiceImpl implements ClientUserService {
    @Resource
    private ClientUserMapper clientUserMapper;

    @Autowired
    private WxMaService wxMaService;

    @Autowired
    private JwtSessionUtil jwtSessionUtil;

    @Override
    public User findUser(Long id) {
        UserExample example = new UserExample();
        example.createCriteria().andIdEqualTo(id);
        return clientUserMapper.selectOneByExample(example);
    }

    @Override
    public AboutMeRsp AboutMe(Long id) {
        User user = findUser(id);
        return AboutMeRsp.ToAboutMe(user);
    }

    @Override
    public User findUserByname(String phone) {
        UserExample example =new UserExample();
        example.createCriteria().andPhoneEqualTo(phone);
        return clientUserMapper.selectOneByExample(example);
    }

    @Override
    public User registe(WxMaJscode2SessionResult sessionInfo) {
        User user = new User();
        user.setOpenid(sessionInfo.getOpenid());
        clientUserMapper.insert(user);
        return user;
    }

    @Override
    public User couvertSecrecyMsg(User user) {
        if (user != null) {
            user.setPwd("");
            user.setSalt("");
        }
        return user;
    }

    @Override
    public User isPhoneAlreadyBinding(WxMaJscode2SessionResult sessionInfo) {
        User user = new User();
        user.setOpenid(sessionInfo.getOpenid());
        clientUserMapper.insert(user);
        return user;
    }

    @Override
    public WxMaJscode2SessionResult getOpenidBycode(MiniGetUserInfoReq miniUserInfoReq) {
        // 获取小程序用户信息
        WxMaJscode2SessionResult sessionInfo;
        try {
            sessionInfo = wxMaService.getUserService().getSessionInfo(miniUserInfoReq.getCode());
        } catch (WxErrorException e) {
            throw new UserException(ErrorCode.USER_GET_WEIXIN_USERINFO);
        }
        if (sessionInfo.getOpenid().isEmpty() || sessionInfo == null) {
            throw new UserException(ErrorCode.USER_GET_WEIXIN_USERINFO);
        }
        return sessionInfo;
    }

    @Override
    public MiniUserInfoRsp setuser(WxMaJscode2SessionResult sessionInfo,String token,User user) {
        MiniUserInfoRsp rsp=new MiniUserInfoRsp();
        rsp.setOpenid(sessionInfo.getOpenid());
        rsp.setToken(token);
        rsp.setId(user.getId());
        rsp.setSessinokey(sessionInfo.getSessionKey());
        return rsp;
    }

    @Override
    public String setJwtToken(User user,ChannelEnum channelEnum,HttpServletRequest request,HttpServletResponse response) {
        JwtUser jwtUser = generateJwtUser(user, channelEnum);

        RedisSession redisSession=jwtSessionUtil.createSession(jwtUser, request, response);
        return redisSession.getToken();
    }

    private JwtUser generateJwtUser(User user, ChannelEnum channelEnum) {
        JwtUser jwtUser = new JwtUser();

        jwtUser.setAnonymous(false);
        jwtUser.setChannel(channelEnum.getCode());
        jwtUser.setUserId(user.getId());
        User user1 = findWxMiniAccountByUserIdOrfail(user.getId());
        jwtUser.setWxOpenid(user1.getOpenid());

        return jwtUser;
    }

    /**
     * 生成盐值
     */

    
    private Supplier<String> generatePwdSalt = () -> {
        String str = "qwertyuiopasdfghjklzxcvbnm1234567890";
        StringBuilder salt = new StringBuilder(5);
        for (int i = 0;i < 5; i++) {
            salt.append(str.charAt(RandomUtils.nextInt(0, str.length())));
        }
        return salt.toString();
    };

    public User findWxMiniAccountByUserIdOrfail(Long userId) {
        User user = findWxMiniAccountByUserId(userId);
        if (user == null) {
            throw new UserException(ErrorCode.WX_MINI_ACCOUNT_NOT_RELATE_DATA);
        }

        return user;
    }

    public User findWxMiniAccountByUserId(Long userId) {
        UserExample example = new UserExample();
        example.createCriteria().andIdEqualTo(userId);
        return clientUserMapper.selectOneByExample(example);
    }
}
